package com.enba.mallapi.module.auth.service.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.enba.boot.core.exception.BizException;
import com.enba.mallapi.constant.CommonConstant;
import com.enba.mallapi.module.auth.controller.ex.UserExCode;
import com.enba.mallapi.module.auth.controller.req.RoleAddUpdateReq;
import com.enba.mallapi.module.auth.controller.req.SaveRolePermissionReq;
import com.enba.mallapi.module.auth.entity.Role;
import com.enba.mallapi.module.auth.entity.RoleMenu;
import com.enba.mallapi.module.auth.entity.UserRole;
import com.enba.mallapi.module.auth.mapper.RoleMapper;
import com.enba.mallapi.module.auth.mapper.UserRoleMapper;
import com.enba.mallapi.module.auth.service.IRoleMenuService;
import com.enba.mallapi.module.auth.service.IRoleService;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 角色表 服务实现类
 *
 * @author 恩爸编程
 * @since 2025-02-28
 */
@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

  @Autowired private IRoleMenuService roleMenuService;
  @Autowired private UserRoleMapper userRoleMapper;

  @Override
  public boolean saveOrUpdate(RoleAddUpdateReq req) {
    Long id = req.getId();

    if (id == null) {
      // 判断角色名是否已存在
      Role one =
          this.getOne(
              Wrappers.<Role>lambdaQuery()
                  .eq(Role::getRoleName, req.getRoleName())
                  .eq(Role::getDeleted, CommonConstant.no));

      if (one != null) {
        // 角色名已存在
        BizException.throwEx(UserExCode.ROLE_NAME_EXIST);
      }

      // 校验角色权限字符
      if (this.exists(Wrappers.<Role>lambdaQuery().eq(Role::getRoleKey, req.getRoleKey()))) {
        UserExCode.ROLE_KEY_EXIST.throwEx();
      }

      // 新增
      Role role = new Role();
      role.setRoleName(req.getRoleName());
      role.setRoleKey(req.getRoleKey());
      role.setRemark(req.getRemark());
      role.setStatus(req.getStatus());
      return this.save(role);
    }

    // 根据角色权限标识获取角色
    Role roleByKey =
        this.baseMapper.selectOne(
            Wrappers.<Role>lambdaQuery().eq(Role::getRoleKey, req.getRoleKey()));

    // 校验角色权限字符
    if (Objects.nonNull(roleByKey) && !roleByKey.getId().equals(id)) {
      UserExCode.ROLE_KEY_EXIST.throwEx();
    }

    Role role = new Role();
    role.setId(id);
    role.setRoleName(req.getRoleName());
    role.setRoleKey(req.getRoleKey());
    role.setRemark(req.getRemark());
    role.setStatus(req.getStatus());
    return this.updateById(role);
  }

  @Override
  public boolean saveRolePermission(SaveRolePermissionReq req) {
    // 角色ID
    Long roleId = req.getRoleId();

    // 检查角色
    if (!this.getBaseMapper().exists(Wrappers.<Role>lambdaQuery().eq(Role::getId, roleId))) {
      BizException.throwEx(UserExCode.ROLE_NOT_EXIST);
    }

    // 权限ID集合
    Set<Long> menuIdSet = req.getMenuIdSet();

    // 先解除绑定关系
    roleMenuService.remove(Wrappers.<RoleMenu>lambdaQuery().eq(RoleMenu::getRoleId, roleId));

    // 重新绑定关系
    Set<RoleMenu> roleMenuSet =
        menuIdSet.stream()
            .map(
                menuId -> {
                  RoleMenu roleMenu = new RoleMenu();
                  roleMenu.setRoleId(roleId);
                  roleMenu.setMenuId(menuId);
                  return roleMenu;
                })
            .collect(Collectors.toSet());
    return roleMenuService.saveBatch(roleMenuSet);
  }

  @Override
  public Set<Long> getUserRoleIdSet(Long userId) {
    List<UserRole> userRoleList =
        userRoleMapper.selectList(Wrappers.<UserRole>lambdaQuery().eq(UserRole::getUserId, userId));

    return userRoleList.stream().map(UserRole::getRoleId).collect(Collectors.toSet());
  }

  @Transactional(rollbackFor = Exception.class)
  @Override
  public boolean deleteBatch(List<Integer> ids) {
    // 如果角色已绑定用户，禁止删除角色
    if (userRoleMapper.exists(Wrappers.<UserRole>lambdaQuery().in(UserRole::getRoleId, ids))) {
      BizException.throwEx(UserExCode.ROLE_BIND_USER);
    }

    if (this.removeBatchByIds(ids)) {
      // 删除角色菜单关系
      return roleMenuService.remove(Wrappers.<RoleMenu>lambdaQuery().in(RoleMenu::getRoleId, ids));
    }
    return false;
  }

  @Transactional(rollbackFor = Exception.class)
  @Override
  public boolean delete(Integer id) {
    // 如果角色已绑定用户，禁止删除角色
    if (userRoleMapper.exists(Wrappers.<UserRole>lambdaQuery().eq(UserRole::getRoleId, id))) {
      BizException.throwEx(UserExCode.ROLE_BIND_USER);
    }

    if (this.removeById(id)) {
      // 删除角色菜单关系
      return roleMenuService.remove(Wrappers.<RoleMenu>lambdaQuery().eq(RoleMenu::getRoleId, id));
    }
    return false;
  }
}
